Script.ReloadScript("scripts/Utils/EntityUtils.lua")

-- Basic entity
SceneObject = {
	Properties = {
		soclasses_SmartObjectClass = "",
		--bAutoGenAIHidePts = 0,
		bMissionCritical = 0,
		bCanTriggerAreas = 0,
		DmgFactorWhenCollidingAI = 1,
				
		object_Model = "objects/default/primitive_sphere.cgf",
		Physics = {
			bPhysicalize = 1, -- True if object should be physicalized at all.
			bRigidBody = 1, -- True if rigid body, False if static.
			bPushableByPlayers = 1,
		
			Density = -1,
			Mass = -1,
		},
		
		bExcludeCover=0,
	},

	Client = {},
	Server = {},
	
	-- Temp.
	_Flags = {},
	
		Editor={
		Icon = "physicsobject.bmp",
		IconOnTop=1,
	  },
			
}

local Physics_DX9MP_Simple = {
	bPhysicalize = 1, -- True if object should be physicalized at all.
	bPushableByPlayers = 0,
		
	Density = 0,
	Mass = 0,
		
}


------------------------------------------------------------------------------------------------------
function SceneObject:OnSpawn()
	self.bRigidBodyActive = 1;

	self:SetFromProperties();	
end

-- Called by gamerules --- resets entity if initial transform is available -------------------------
function SceneObject:Event_Reset()
	self:OnReset();
	BroadcastEvent(self, "Reset");
	
	if (self.InitialPosition) then
		self:SetPos(self.InitialPosition);
	end

	if (self.InitialAngles) then
		self:SetWorldAngles(self.InitialAngles);
	end

	if (self.InitialScale) then
		self:SetScale(self.InitialScale);
	end
end

-- Called by gamerules ------------------------------------------------------------------------------
-- set initial transform so you can use Event_Reset to return objects to their positions ------------
------------------------------------------------------------------------------------------------------
function SceneObject:StoreInitialTransform()
	self.InitialScale = self:GetScale();
	self.InitialAngles = self:GetWorldAngles();
	self.InitialPosition = self:GetPos();
end

------------------------------------------------------------------------------------------------------
function SceneObject:SetFromProperties()
	local Properties = self.Properties;

	if (Properties.object_Model == "") then
		do return end;
	end
	
	self.freezable=tonumber(Properties.bFreezable)~=0;
	
	self:LoadObject(0,Properties.object_Model);
	--self:CharacterUpdateOnRender(0,1); -- If it is a character force it to update on render.

	
	if (Properties.Physics.bPhysicalize == 1) then
		self:PhysicalizeThis();
	end

	-- Mark AI hideable flag.
	if (Properties.bAutoGenAIHidePts == 1) then
		self:SetFlags(ENTITY_FLAG_AI_HIDEABLE, 0); -- set
	else
		self:SetFlags(ENTITY_FLAG_AI_HIDEABLE, 2); -- remove
	end
	
	if (self.Properties.bCanTriggerAreas == 1) then
		self:SetFlags(ENTITY_FLAG_TRIGGER_AREAS, 0); -- set
	else
		self:SetFlags(ENTITY_FLAG_TRIGGER_AREAS, 2); -- remove
	end
end

------------------------------------------------------------------------------------------------------
function SceneObject:IsRigidBody()

	local Properties = self.Properties;
	local Mass = Properties.Mass; 
  local Density = Properties.Density;
  if (Mass == 0 or Density == 0 or Properties.bPhysicalize ~= 1) then 
  	return false;
  end
  return true;
end

------------------------------------------------------------------------------------------------------
function SceneObject:PhysicalizeThis()
	-- Init physics.
	local Physics = self.Properties.Physics;
	if (CryAction.IsImmersivenessEnabled() == 0) then
		Physics = Physics_DX9MP_Simple;
	end
	EntityCommon.PhysicalizeRigid( self,0,Physics,self.bRigidBodyActive );
end

------------------------------------------------------------------------------------------------------
-- OnPropertyChange called only by the editor.
------------------------------------------------------------------------------------------------------
function SceneObject:OnPropertyChange()
  -- if the properties are changed, we force a reset in the __usable
  if (self.__usable) then
    if (self.__origUsable ~= self.Properties.bUsable or self.__origPickable ~= self.Properties.bPickable) then
      self.__usable = nil;
    end
  end
	self:SetFromProperties();
end

------------------------------------------------------------------------------------------------------
-- OnReset called only by the editor.
------------------------------------------------------------------------------------------------------
function SceneObject:OnReset()
	self:ResetOnUsed()
	
	local PhysProps = self.Properties.Physics;
	if (PhysProps.bPhysicalize == 1) then
		self:PhysicalizeThis();
		self:AwakePhysics(0);
	end
end

------------------------------------------------------------------------------------------------------
function SceneObject:Event_Remove()
--	self:Hide(1);
	self:DrawSlot(0,0);
	self:DestroyPhysics();
	self:ActivateOutput( "Remove", true );
end


------------------------------------------------------------------------------------------------------
function SceneObject:Event_Hide()
	self:Hide(1);
	self:ActivateOutput( "Hide", true );
	if CurrentCinematicName then
		Log("%.3f %s %s : Event_Hide", _time, CurrentCinematicName, self:GetName() );
	end
	--self:DrawObject(0,0);
	--self:DestroyPhysics();
end

------------------------------------------------------------------------------------------------------
function SceneObject:Event_UnHide()
	self:Hide(0);
	self:ActivateOutput( "UnHide", true );
	if CurrentCinematicName then
		Log("%.3f %s %s : Event_UnHide", _time, CurrentCinematicName, self:GetName() );
	end
	--self:DrawObject(0,1);
	--self:SetPhysicsProperties( 1,self.bRigidBodyActive );
end

------------------------------------------------------------------------------------------------------
function SceneObject:Event_Ragdollize()  
	self:RagDollize(0);
	self:ActivateOutput( "Ragdollized", true );
	if (self.Event_RagdollizeDerived) then
		self:Event_RagdollizeDerived();
	end
end

------------------------------------------------------------------------------------------------------
function SceneObject.Client:OnPhysicsBreak( vPos,nPartId,nOtherPartId )
	self:ActivateOutput("Break",nPartId+1 );
end


------------------------------------------------------------------------------------------------------
--function SceneObject:OnDamage( hit )
--	if( hit.ipart and hit.ipart>=0 ) then
--		self:AddImpulse( hit.ipart, hit.pos, hit.dir, hit.impact_force_mul );
--	end
--end

function SceneObject:IsUsable(user)
	local ret = nil
	-- From EntityUtils.lua
	if not self.__usable then self.__usable = self.Properties.bUsable end
	
	local mp = System.IsMultiplayer();
	if(mp and mp~=0) then
		return 0;
	end

	if (self.__usable == 1) then
		ret = 2
	else
		local PhysProps = self.Properties.Physics;
		if (self:IsRigidBody() == true and user and user.CanGrabObject) then
			ret = user:CanGrabObject(self)
		end
	end
		
	return ret or 0
end

SceneObject.FlowEvents =
{
	Inputs =
	{
		Used = { SceneObject.Event_Used, "bool" },
		EnableUsable = { SceneObject.Event_EnableUsable, "bool" },
		DisableUsable = { SceneObject.Event_DisableUsable, "bool" },

		Hide = { SceneObject.Event_Hide, "bool" },
		UnHide = { SceneObject.Event_UnHide, "bool" },
		Remove = { SceneObject.Event_Remove, "bool" },
		Ragdollize = { SceneObject.Event_Ragdollize, "bool" },
	},
	Outputs =
	{
		Used = "bool",
		EnableUsable = "bool",
		DisableUsable = "bool",
		Activate = "bool",
		Hide = "bool",
		UnHide = "bool",
		Remove = "bool",
		Ragdollized = "bool",		
		Break = "int",
	},
}